﻿using JavaDevToys.Rcl.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using static System.Collections.Specialized.BitVector32;
using Section = JavaDevToys.Rcl.Models.Section;

namespace JavaDevToys.Rcl.Service.Impl
{
    public class ApiInfoParser: IApiInfoParser
    {
        public ApiInfo Parse(string _content)
        {
            ApiInfo apiInfo = new ApiInfo();

            // 分割内容为行
            string[] lines = _content.Split(new[] { "\r\n", "\n" }, StringSplitOptions.None);
            // 使用状态机来跟踪当前解析的部分

            Models.Section currentSection = Models.Section.None;
            // 临时变量
            Regex sectionRegex = new Regex(@"^(API名称|类名|方法名|是否分页|规则描述|入参|出参)\s+(.+)$");
            Regex paramHeaderRegex = new Regex(@"^\s*参数描述\s+参数名\s+必填\s+数据类型\s+备注\s+最后修改时间$");
            Regex paramRowRegex = new Regex(@"^\s*(.+?)\s+(.+?)\s+([YN]?)\s+(\S+)\s*(.*?)\s*$");
            Regex dtoParamRegex = new Regex(@"^【End-.*列表】$");
            Regex dto2ParamRegex = new Regex(@"End-[\u4e00-\u9fa5a-zA-Z]+列表", RegexOptions.IgnoreCase);
            Regex dto3ParamRegex = new Regex(@"End-[\u4e00-\u9fa5a-zA-Z]", RegexOptions.IgnoreCase);
            Regex dto4ParamRegex = new Regex(@"[\u4e00-\u9fa5a-zA-Z]-End", RegexOptions.IgnoreCase);
            List<string> dtoParamsName = new List<string>();
            bool requestBegin = false;
            bool responseBegin = false;
            int titleIndex = 0;
            
            for (int i = 0; i < lines.Length; i++)
            {
                var isInDto = false;
                var rawLine = lines[i];
                string lastParameterName = string.Empty;
                string line = rawLine.Trim();
                if (string.IsNullOrEmpty(line))
                    continue;
                if (dtoParamRegex.IsMatch(line)|| dto2ParamRegex.IsMatch(line)|| dto3ParamRegex.IsMatch(line)|| dto4ParamRegex.IsMatch(line))
                {
                    if(dtoParamsName.Count>0)
                        dtoParamsName.Remove(dtoParamsName.Last());
                }
                // 检查是否为新的部分
                var sectionMatch = sectionRegex.Match(line);
                if (sectionMatch.Success)
                {
                    string sectionName = sectionMatch.Groups[1].Value.Trim();
                    string sectionContent = sectionMatch.Groups[2].Value.Trim();

                    switch (sectionName)
                    {
                        case "API名称":
                            if (requestBegin || responseBegin)
                                break;
                            apiInfo.ApiName = sectionContent;
                            currentSection = Section.ApiInfo;
                            break;
                        case "类名":
                            if (requestBegin || responseBegin)
                                break;
                            apiInfo.ClassName = sectionContent=="Interface"?"exinterface": sectionContent;
                            break;
                        case "方法名":
                            if (requestBegin || responseBegin)
                                break;
                            apiInfo.MethodName = sectionContent;
                            break;
                        case "是否分页":
                            if (requestBegin || responseBegin)
                                break;
                            apiInfo.IsPaginated = sectionContent.Equals("Y", StringComparison.OrdinalIgnoreCase);
                            break;
                        case "规则描述":
                            if (requestBegin || responseBegin)
                                break;
                            apiInfo.Description = sectionContent.Trim('"');
                            break;
                        case "入参":
                            currentSection = Section.RequestParams;
                            requestBegin = true;
                            break;
                        case "出参":
                            currentSection = Section.ResponseParams;
                            responseBegin = true;
                            titleIndex = i;
                            break;
                        default:
                            currentSection = Section.None;
                            break;
                    }
                    continue;
                }

                // 根据当前部分解析
                switch (currentSection)
                {
                    case Section.RequestParams:
                    case Section.ResponseParams:
                        // 解析参数表头，忽略
                        if (paramHeaderRegex.IsMatch(line))
                        {
                            continue;
                        }

                        // 解析参数行
                        var paramMatch = paramRowRegex.Match(line);
                        if (paramMatch.Success)
                        {
                            string description = paramMatch.Groups[1].Value.Trim();
                            string name = paramMatch.Groups[2].Value.Trim();
                            bool isRequired = paramMatch.Groups[3].Value.Trim().Equals("Y", StringComparison.OrdinalIgnoreCase);
                            string dataType = paramMatch.Groups[4].Value.Trim();
                            string remarks = paramMatch.Groups[5].Value.Trim();
                            if (IsComplexList(dataType))
                            {
                                dataType = $"List<{ExtractClassNameFromList(name)}>";

                                if (titleIndex != i - 1)//首个参数为list不添加
                                {
                                    lastParameterName = ExtractClassNameFromList(name);
                                    dtoParamsName.Add(lastParameterName);
                                    if(!apiInfo.DtoParameters.ContainsKey(lastParameterName))
                                        apiInfo.DtoParameters.Add(lastParameterName, new List<ParameterInfo>());
                                    if (dtoParamsName.Count > 1)//已经存在一个嵌套类型了
                                        isInDto = true;
                                }
                                else
                                    continue;
                            }
                            if (IsClass(dataType))
                            {
                                dataType = $"{ExtractClassNameFromClass(name)}";

                                lastParameterName = ExtractClassNameFromClass(name);
                                dtoParamsName.Add(lastParameterName);
                                if (!apiInfo.DtoParameters.ContainsKey(lastParameterName))
                                    apiInfo.DtoParameters.Add(lastParameterName, new List<ParameterInfo>());
                                if (dtoParamsName.Count > 1)//已经存在一个嵌套类型了
                                    isInDto = true;
                            }
                            ParameterInfo param = new ParameterInfo
                            {
                                Description = description,
                                ParameterName = name,
                                IsRequired = isRequired,
                                DataType = dataType,
                                Remarks = remarks
                            };
                            if (dtoParamsName.Count>0&& string.IsNullOrWhiteSpace(lastParameterName))
                            {
                                var dtoParamName=dtoParamsName.Last();
                                if(!apiInfo.DtoParameters[dtoParamName].Any(a=>a.ParameterName== param.ParameterName))
                                    apiInfo.DtoParameters[dtoParamName].Add(param);
                                continue;
                            }
                            if (isInDto)//嵌套类型中的嵌套类型
                            {
                                var dtoParamName = dtoParamsName[dtoParamsName.Count-2];
                                apiInfo.DtoParameters[dtoParamName].Add(param);
                                continue;
                            }
                            if (currentSection == Section.RequestParams)
                            {
                                apiInfo.RequestParameters.Add(param);
                            }
                            else if (currentSection == Section.ResponseParams)
                            {
                                apiInfo.ResponseParameters.Add(param);
                            }
                        }
                        break;
                    default:
                        // 其他部分不处理
                        break;
                }
            }

            return apiInfo;
        }

        private bool IsComplexList(string dataType)
        {
            switch (dataType.ToUpper())
            {
                case "LIST<STRING>":
                case "LIST<INTEGER>":
                case "LIST<BIGDECIMAL>":
                case "LIST<LONG>":
                case "LIST<DATE>":
                    return false;
                default:
                    break;
            }
            return Regex.IsMatch(dataType, @"^List<\w+>$");
        }

        private bool IsClass(string dataType)
        {
            return dataType.ToUpper()=="CLASS";
        }

        private string ExtractClassNameFromList(string dataType)
        {
            var match = Regex.Match(dataType, @"^(\w+)List$");
            if (match.Success)
            {
                return $"{match.Groups[1].Value.Substring(0, 1).ToUpper() + match.Groups[1].Value.Substring(1)}DTO";
            }
            return "UnknownClass";
        }

        private string ExtractClassNameFromClass(string dataType)
        {
            if(string.IsNullOrWhiteSpace(dataType) || dataType.Length<1)
                return "UnknownClass";
            return $"{dataType.Substring(0, 1).ToUpper() + dataType.Substring(1)}DTO";
        }

        public string MapCSharpType(string dataType)
        {
            switch (dataType.ToUpper())
            {
                case "LONG":
                    return "long?";
                case "INTEGER":
                    return "int?";
                case "STRING":
                    return "string";
                case "BIGDECIMAL":
                    return "decimal?";
                case "LONG[]":
                    return "long[]";
                case "STRING[]":
                    return "string[]";
                case "LIST<STRING>":
                    return "List<string>";
                case "LIST<INTEGER>":
                    return "List<int>";
                case "LIST<LONG>":
                    return "List<long>";
                case "DATE":
                case "TIME":
                case "DATETIME":
                    return "DateTime?";
                default:
                    break;
            }
            return dataType;
        }

        public ApiInfo ParseCSharp(string _content)
        {
            ApiInfo apiInfo = new ApiInfo();

            // 分割内容为行
            string[] lines = _content.Split(new[] { "\r\n", "\n" }, StringSplitOptions.None);
            // 使用状态机来跟踪当前解析的部分

            Models.Section currentSection = Models.Section.None;
            // 临时变量
            Regex sectionRegex = new Regex(@"^(API名称|类名|方法名|是否分页|规则描述|入参|出参)\s+(.+)$");
            Regex paramHeaderRegex = new Regex(@"^\s*参数描述\s+参数名\s+必填\s+数据类型\s+备注\s+最后修改时间$");
            Regex paramRowRegex = new Regex(@"^\s*(.+?)\s+(.+?)\s+([YN]?)\s+(\S+)\s*(.*?)\s*$");
            Regex dtoParamRegex = new Regex(@"^【End-.*列表】$");
            Regex dto2ParamRegex = new Regex(@"End-[\u4e00-\u9fa5a-zA-Z]+列表");
            Regex dto3ParamRegex = new Regex(@"End-[\u4e00-\u9fa5a-zA-Z]");
            List<string> dtoParamsName = new List<string>();
            bool requestBegin = false;
            bool responseBegin = false;
            int titleIndex = 0;

            for (int i = 0; i < lines.Length; i++)
            {
                var isInDto = false;
                var rawLine = lines[i];
                string lastParameterName = string.Empty;
                string line = rawLine.Trim();
                if (string.IsNullOrEmpty(line))
                    continue;
                if (dtoParamRegex.IsMatch(line) || dto2ParamRegex.IsMatch(line) || dto3ParamRegex.IsMatch(line))
                {
                    if (dtoParamsName.Count > 0)
                        dtoParamsName.Remove(dtoParamsName.Last());
                }
                // 检查是否为新的部分
                var sectionMatch = sectionRegex.Match(line);
                if (sectionMatch.Success)
                {
                    string sectionName = sectionMatch.Groups[1].Value.Trim();
                    string sectionContent = sectionMatch.Groups[2].Value.Trim();

                    switch (sectionName)
                    {
                        case "API名称":
                            if (requestBegin || responseBegin)
                                break;
                            apiInfo.ApiName = sectionContent;
                            currentSection = Section.ApiInfo;
                            break;
                        case "类名":
                            if (requestBegin || responseBegin)
                                break;
                            apiInfo.ClassName = sectionContent == "Interface" ? "exinterface" : sectionContent;
                            break;
                        case "方法名":
                            if (requestBegin || responseBegin)
                                break;
                            apiInfo.MethodName = sectionContent;
                            break;
                        case "是否分页":
                            if (requestBegin || responseBegin)
                                break;
                            apiInfo.IsPaginated = sectionContent.Equals("Y", StringComparison.OrdinalIgnoreCase);
                            break;
                        case "规则描述":
                            if (requestBegin || responseBegin)
                                break;
                            apiInfo.Description = sectionContent.Trim('"');
                            break;
                        case "入参":
                            currentSection = Section.RequestParams;
                            requestBegin = true;
                            break;
                        case "出参":
                            currentSection = Section.ResponseParams;
                            responseBegin = true;
                            titleIndex = i;
                            break;
                        default:
                            currentSection = Section.None;
                            break;
                    }
                    continue;
                }

                // 根据当前部分解析
                switch (currentSection)
                {
                    case Section.RequestParams:
                    case Section.ResponseParams:
                        // 解析参数表头，忽略
                        if (paramHeaderRegex.IsMatch(line))
                        {
                            continue;
                        }

                        // 解析参数行
                        var paramMatch = paramRowRegex.Match(line);
                        if (paramMatch.Success)
                        {
                            string description = paramMatch.Groups[1].Value.Trim();
                            string name = paramMatch.Groups[2].Value.Trim();
                            bool isRequired = paramMatch.Groups[3].Value.Trim().Equals("Y", StringComparison.OrdinalIgnoreCase);
                            string dataType = MapCSharpType(paramMatch.Groups[4].Value.Trim());
                            string remarks = paramMatch.Groups[5].Value.Trim();
                            if (IsComplexList(dataType))
                            {
                                dataType = $"List<{ExtractClassNameFromList(name)}>";

                                if (titleIndex != i - 1)//首个参数为list不添加
                                {
                                    lastParameterName = ExtractClassNameFromList(name);
                                    dtoParamsName.Add(lastParameterName);
                                    if (!apiInfo.DtoParameters.ContainsKey(lastParameterName))
                                        apiInfo.DtoParameters.Add(lastParameterName, new List<ParameterInfo>());
                                    if (dtoParamsName.Count > 1)//已经存在一个嵌套类型了
                                        isInDto = true;
                                }
                                else
                                    continue;
                            }
                            if (IsClass(dataType))
                            {
                                dataType = $"{ExtractClassNameFromClass(name)}";

                                lastParameterName = ExtractClassNameFromClass(name);
                                dtoParamsName.Add(lastParameterName);
                                if (!apiInfo.DtoParameters.ContainsKey(lastParameterName))
                                    apiInfo.DtoParameters.Add(lastParameterName, new List<ParameterInfo>());
                                if (dtoParamsName.Count > 1)//已经存在一个嵌套类型了
                                    isInDto = true;
                            }
                            ParameterInfo param = new ParameterInfo
                            {
                                Description = description,
                                ParameterName = name,
                                IsRequired = isRequired,
                                DataType = dataType,
                                Remarks = remarks
                            };
                            if (dtoParamsName.Count > 0 && string.IsNullOrWhiteSpace(lastParameterName))
                            {
                                var dtoParamName = dtoParamsName.Last();
                                if (!apiInfo.DtoParameters[dtoParamName].Any(a => a.ParameterName == param.ParameterName))
                                    apiInfo.DtoParameters[dtoParamName].Add(param);
                                continue;
                            }
                            if (isInDto)//嵌套类型中的嵌套类型
                            {
                                var dtoParamName = dtoParamsName[dtoParamsName.Count - 2];
                                apiInfo.DtoParameters[dtoParamName].Add(param);
                                continue;
                            }
                            if (currentSection == Section.RequestParams)
                            {
                                apiInfo.RequestParameters.Add(param);
                            }
                            else if (currentSection == Section.ResponseParams)
                            {
                                apiInfo.ResponseParameters.Add(param);
                            }
                        }
                        break;
                    default:
                        // 其他部分不处理
                        break;
                }
            }

            return apiInfo;
        }
    }
}
